'use strict';
const md5 = require('md5');
const got = require('got');
const wx_server_sdk = require('wx-server-sdk');
wx_server_sdk.init({
    env: 'shifu-map-tvsh8'
    // env: 'other'
});

const db = wx_server_sdk.database({ throwOnNotFound: false });
const dbCommand = db.command;

var nowTime = null;

var jimiBasicParam = {
    // method: 'jimi.oauth.token.get',
    timestamp: '',
    app_key: process.env.app_key,
    v: '0.9',
    sign_method: 'md5',
    format: 'json',
}
var expires_in = 3800;
//云函数入口
async function funcMain(event, context) {
    context.callbackWaitsForEmptyEventLoop = false; //针对node 10.15版本的设置,避免一些函数跑空造成拖延时间
    nowTime = getBeijingTime();
    jimiBasicParam.timestamp = nowTime.time;
    console.log('函数参数', event);

    if (event.hasOwnProperty('Type') && event.Type == 'timer' &&
        event.hasOwnProperty('TriggerName')) {
        if (event.TriggerName == 'refreshToken') {

            //每小时刷新token
            return await refreshToken();
        } else if (event.TriggerName == 'refreshLocation') {
            var allGps = await getNowLocation_all();
            if (allGps.code == 0) {

                return await db.collection('jimiGps').add({
                    data: {
                        beijingTime: nowTime.time,
                        beijingTs: nowTime.ts,
                        data: allGps.data
                    }
                })
            } else {
                console.log('批量获取位置失败', allGps);
                if (allGps.code != -1) {
                    await db.collection('jimiGps').add({
                        data: {

                            beijingTime: nowTime.time,
                            beijingTs: nowTime.ts,
                            errData: allGps.data
                        }
                    })

                    await refreshToken();
                    return await funcMain(event, context); //循环调用
                } else {
                    return {
                        code: -99,
                        errMsg: '定时批量获取位置失败'
                    }
                }
            }
        }

    } else if (event.hasOwnProperty('actionType') && event.actionType == '刷新') {
        var tcbData = await db.collection('jimiGps').orderBy('beijingTs', 'desc')
            .limit(2).get();
        return tcbData;
    } else if (event.hasOwnProperty('actionType') && event.actionType == '刷新token') {
        return await refreshToken();
    } else if (event.hasOwnProperty('actionType') && event.actionType == '重新获取token') {
        return await gnrtToken();
    }

    return;
}

function md5Pwd(pwd) {

    var digestMD5 = require('digest-js');
    digestMD5 = new digestMD5.MD5();
    digestMD5.update(pwd);
    // digestMD5.digest();

    function buf2hex(buffer) {
        return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
    }
    var user_pwd_md5 = digestMD5.finalize();
    return buf2hex(user_pwd_md5);
}

async function gnrtToken() {
    var gotParams = deepCopy(jimiBasicParam);
    gotParams.method = 'jimi.oauth.token.get';
    gotParams.user_id = process.env.user_id;
    gotParams.user_pwd_md5 = md5Pwd(process.env.user_pwd);
    gotParams.expires_in = expires_in + ''; //每小时更新一次,此数值比3600秒大即可

    var access_token = await gotJob(gotParams);
    // console.log('gnrtToken access_token', access_token);

    if (access_token.code == 0) {
        access_token = access_token.result;

        var failedTime = getBeijingTime(nowTime.ts + expires_in * 1000);
        await db.collection('mina').doc('jimiToken').update({
            data: {
                access_token: access_token.accessToken,
                refresh_token: access_token.refreshToken,
                createdTime: nowTime.time,
                createdTs: nowTime.ts,
                failedTime: failedTime.time,
                failedTs: failedTime.ts,
            }
        })

        return {
            code: 0,
            data: access_token
        }
    } else {
        console.log('从几米获取token失败', access_token);
        return {
            code: -1,
            errMsg: '从几米获取token失败',
            data: access_token,
        };
    }
}

async function getTokenFromTcb() {
    var access_token = await db.collection('mina').doc('jimiToken').get();
    // console.log('jimiToken数据', access_token);

    if (access_token.errMsg == 'document.get:ok' && access_token.data &&
        access_token.data.access_token) {
        access_token = access_token.data;

        if (access_token.failedTs < nowTime.ts) {
            //手动刷新
            var newToken = await gnrtToken();
            if (newToken.code == 0) {
                access_token = newToken.data;
            }
        }
    }

    return {
        code: 0,
        data: access_token
    }
}

async function refreshToken() {
    var tokenData = await getTokenFromTcb();

    //若中间断过,导致refresh_token密码已经过期,则重新生成token
    if (tokenData.data.failedTs < nowTime.ts) {
        return await gnrtToken();
    }

    var gotParams = deepCopy(jimiBasicParam);
    gotParams.method = 'jimi.oauth.token.refresh';
    gotParams.access_token = tokenData.data.access_token;
    gotParams.refresh_token = tokenData.data.refresh_token;
    gotParams.expires_in = expires_in + '';

    var newData = await gotJob(gotParams);
    if (newData.code != 0) {
        //异常,则重新生成token
        return await gnrtToken();
    }

    var failedTime = getBeijingTime(nowTime.ts + expires_in * 1000);
    console.log('刷新后的token', newData);

    var updateData = await db.collection('mina').doc('jimiToken').update({
        data: {
            access_token: newData.result.accessToken,
            refresh_token: newData.result.refreshToken,
            createdTime: nowTime.time,
            createdTs: nowTime.ts,
            failedTime: failedTime.time,
            failedTs: failedTime.ts,
        }
    });

    return {
        code: 0,
        data: {
            access_token: newData.result.accessToken,
            refresh_token: newData.result.refreshToken,
        }
    };
}

async function getTrack(imei) {

    var tokenData = await getTokenFromTcb();

    if (tokenData.code == -1) {
        return {
            code: -1,
            errMsg: 'getTrack在调用getTokenFromTcb时出错',
            data: tokenData
        }
    }

    var gotParams = deepCopy(jimiBasicParam);
    gotParams.method = 'jimi.device.track.list';
    gotParams.access_token = tokenData.data.access_token;
    gotParams.imei = imei;
    gotParams.begin_time = getBeijingTime(nowTime.ts - 7200000).time;
    gotParams.end_time = nowTime.time;
    // console.log('getTrack参数', gotParams);

    var track = await gotJob(gotParams);
    // console.log('获取的名下所有GPS的数据', track);

    if (track.code != 0) {
        return {
            code: -1,
            errMsg: '从几米获得历史轨迹时,出错',
            data: track,
        }
    }

    track = track.result;
    const coordtransform = require('coordtransform');

    var data_i = {
        imei: '888',
        deviceName: 'GT220-888', //可以在web端修改
        icon: 'automobile',
        status: '1',
        posType: 'GPS',
        lat: 39.888,
        lng: 116.888,
        hbTime: '2021-02-22 09:24:17',
        accStatus: '0',
        gpsNum: '11',
        powerValue: null,
        powerStatus: '1',
        speed: '19',
        gpsTime: '2021-02-21 17:20:54',
        direction: '147',
        activationFlag: '1',
        expireFlag: '1',
        electQuantity: '',
        mileage: '146176.6453185255'
    }

    var locArray = [];
    for (var i = 0; i < track.length; i++) {
        locArray = coordtransform.wgs84togcj02(track[i].lng, track[i].lat);
        track[i].longitude = locArray[0];
        track[i].latitude = locArray[1];
    }
    return {
        code: 0,
        data: track
    };
}

async function getNowLocation_all() {
    var tokenData = await getTokenFromTcb();

    if (tokenData.code == -1) {
        return {
            code: -1,
            errMsg: 'getNowLocation_all在调用getTokenFromTcb时出错',
            data: tokenData
        }
    }

    var gotParams = deepCopy(jimiBasicParam);
    gotParams.method = 'jimi.user.device.location.list';
    gotParams.access_token = tokenData.data.access_token;
    gotParams.target = process.env.user_id;
    // gotParams.map_type = 'GOOGLE';
    var allGps = await gotJob(gotParams);
    // console.log('获取的名下所有GPS的数据', allGps);

    if (allGps.code != 0) {
        return {
            code: -1,
            errMsg: '从几米获得全部GPS现在数据时,出错',
            data: allGps,
        }
    }

    allGps = allGps.result;
    const coordtransform = require('coordtransform');

    var data_i = {
        imei: '888',
        deviceName: 'GT220-888', //可以在web端修改
        icon: 'automobile',
        status: '1',
        posType: 'GPS',
        lat: 39.888,
        lng: 116.888,
        hbTime: '2021-02-22 09:24:17',
        accStatus: '0',
        gpsNum: '11',
        powerValue: null,
        powerStatus: '1',
        speed: '19',
        gpsTime: '2021-02-21 17:20:54',
        direction: '147',
        activationFlag: '1',
        expireFlag: '1',
        electQuantity: '',
        mileage: '146176.6453185255'
    }

    var locArray = [];
    for (var i = 0; i < allGps.length; i++) {
        locArray = coordtransform.wgs84togcj02(allGps[i].lng, allGps[i].lat);

        allGps[i] = {
            imei: allGps[i].imei,
            deviceName: allGps[i].deviceName,
            status: allGps[i].status,
            longitude: locArray[0],
            latitude: locArray[1],
            hbTime: allGps[i].hbTime,
            speed: allGps[i].speed,
            gpsTime: allGps[i].gpsTime,
            direction: allGps[i].direction,
        }
    }
    return {
        code: 0,
        data: allGps
    };
}

async function gotJob(params) {

    var url = 'http://open.aichezaixian.com/route/rest?';
    for (var key in params) {
        url += '&' + key + '=' + params[key];
    }
    url = url.replace('?&', '?');

    var jimiResult = {};
    try {
        jimiResult = await got(url, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            // body: params,
            json: true,
        })
        jimiResult = jimiResult.body;

        console.log('几米接口返回数据', jimiResult);
        if (jimiResult.code != 0) {
            if (jimiResult.code == 1004) {
                await refreshToken();
                return await gotJob(params);
            }
        }
        return jimiResult;
    } catch (e) {
        console.log('gotJob失败 url', url, jimiResult);

        return {
            code: -1,
            errMsg: 'gotJob失败',
            data: {
                beijingTs: nowTime.ts,
                beijingTime: nowTime.time,
                url
            }
        }
    }
    // console.log(url, '返回的结果', jimiResult.body);
}

function deepCopy(o) {
    if (o instanceof Array) {
        var n = [];
        for (var i = 0; i < o.length; ++i) {
            n[i] = deepCopy(o[i]);
        }
        return n;

    } else if (o instanceof Object) {
        var n = {}
        for (var i in o) {
            n[i] = deepCopy(o[i]);
        }
        return n;
    } else {
        return o;
    }
}

//获取当前时间戳
function getNowTimestamp() {
    return new Date().getTime();
}

//生成时间数据包
function getBeijingTime(localTs) {
    var time_ts = localTs;
    if (typeof(localTs) != 'number' || localTs == 0) {
        time_ts = getNowTimestamp();
    }

    var time = tsToDateStr(time_ts);

    return {
        ts: time_ts,
        time,
    };
}

//将时间戳生成北京时间的字符串时间
function tsToDateStr(ts_para) {
    //在此弥补时差
    var time_ts = new Date(ts_para + 8 * 3600000);

    // console.log('用于制作中文的ts', time_ts.getTime());

    var time_str = time_ts.getFullYear() + '-';

    if ((time_ts.getMonth() + 1) < 10) {
        time_str += '0';
    }
    time_str += '' + (time_ts.getMonth() + 1) + '-';


    if (time_ts.getDate() < 10) {
        time_str += '0';
    }
    time_str += '' + time_ts.getDate() + ' ';


    if (time_ts.getHours() < 10) {
        time_str += '0';
    }
    time_str += '' + time_ts.getHours() + ':';

    if (time_ts.getMinutes() < 10) {
        time_str += '0';
    }
    time_str += '' + time_ts.getMinutes() + ':';

    if (time_ts.getSeconds() < 10) {
        time_str += '0';
    }
    time_str += '' + time_ts.getSeconds(); // + ':' + time_ts.getMilliseconds();

    return time_str;
}


exports.main = funcMain